import input from './input'
import inputDate from './inputDate'
import select from './select'
import textarea from './textarea'
import radio from './radio'
import CKeditor from './CKeditor'
import uploadFileEx from './uploadFileEx'
import chooseBase from './chooseBase'
import checkList from '../other/checkList'
import util from '../other/util'
import alert from '../other/alert'


var formElementMapping = {
    input: input,
    checkList: checkList,
    inputDate: inputDate,
    select: select,
    textarea: textarea,
    radio: radio,
    CKeditor: CKeditor,
    chooseBase: chooseBase,
    uploadFileEx: uploadFileEx,
};

var formEvent = function (options) {
    options = options || {};
    var form = function () { };
    form.prototype.labelwidth = options.labelwidth || 120;
    form.prototype.$html = $('<div class="FUI-form layui-form"></div>');
    form.prototype.$event = {
        onError: options.onError || function () { },
        onScrollError: options.onScrollError || function () { },
    };
    form.prototype.$oldData = {};
    form.prototype.$type = options.type || 'mergeByOldData';
    form.prototype.set = function (data) {
        if (this.$type == 'onlyChange') {
            this.$oldData = {};
            for (var key in data) {
                if (this.hasOwnProperty(key) && data.hasOwnProperty(key)) {
                    this[key].set(data[key], true);
                    this.$oldData[key] = data[key];
                }
            };
        } else if (this.$type == 'mergeByChange') {
            this.$oldData = data;
            for (var key in data) {
                if (this.hasOwnProperty(key) && data.hasOwnProperty(key)) {
                    this[key].set(data[key], true);
                }
            };
        } else {
            this.$oldData = data;
            for (var key in data) {
                if (this.hasOwnProperty(key) && data.hasOwnProperty(key)) {
                    this[key].set(data[key], true);
                }
            };
        };
    };
    form.prototype.$formElementKey = [];
    form.prototype.$removeFormElement = function () {
        for (let i = 0; i < this.$formElementKey.length; i++) {
            const key = this.$formElementKey[i];
            if (this.hasOwnProperty(key)) {
                this[key].html.remove()
                delete this[key];
            };
        };
        this.$formElementKey = [];
    };
    form.prototype.$setOptions = function (options) {
        this.$removeFormElement();
        for (let i = 0; i < options.length; i++) {
            const formArray = options[i];
            this.$addTemplate(formArray);
        };
    };
    form.prototype.$addTemplate = function (itemArray) {
        var html = $('<div class="FUI-form-row layui-row"></div>');
        for (let i = 0; i < itemArray.length; i++) {
            let element = itemArray[i];
            let itemHtml = $('<div class="layui-col-md' + (element.col || 12) + '"></div>');
            let hasSup = ((element.verify && element.verify.rules.indexOf('notNull') != -1) || !!element.required) ? '<sup>*</sup>' : '<sup>&nbsp;</sup>';
            let lable = element.formlabel ? element.formlabel : '';
            let formHtml = ''
            formHtml += '<div class="layui-form-item FUI-form-item">';
            formHtml += '    <label class="layui-form-label" style="width:' + this.labelwidth + 'px">' + hasSup + lable + '</label>';
            formHtml += '    <div class="layui-input-block" style="margin-left:' + (this.labelwidth + 30) + 'px"></div>';
            formHtml += '</div>';
            formHtml = $(formHtml);
            itemHtml.append(formHtml);
            element.el = formHtml.find('.layui-input-block');
            var formErrorMessage = $('<div class="layui-input-block FUI-form-errorMessage" style="margin-left:' + (this.labelwidth + 30) + 'px"></div>');
            formHtml.append(formErrorMessage);
            this.$addItem(element, formErrorMessage);
            html.append(itemHtml);
        };
        this.$html.append(html);
    };
    form.prototype.$addItem = function (options, errorMessageElement) {
        var errorEvent = null;
        if (typeof options.onError == 'function') {
            errorEvent = options.onError
        };
        var item = null;
        var error = (errorMessage, value) => {
            if (errorEvent) {
                errorEvent(errorMessage, value);
            };
            errorMessageElement.text(errorMessage);
            if (this.$event.$onError && typeof this.$event.$onError == 'function') {
                this.$event.$onError(errorMessage, item, options.key);
            };
        };
        options.onError = error;
        if (options.hasOwnProperty('type') && formElementMapping.hasOwnProperty(options.type)) {
            item = new formElementMapping[options.type](options);
        } else {
            item = new options.object(options, this);
        };

        if (typeof item.hideErrorStyle == 'function') {
            var hideErrorStyle = item.hideErrorStyle;
            item.hideErrorStyle = function () {
                errorMessageElement.empty();
                hideErrorStyle.call(item);
            };
        };

        this.$formElementKey.push(options.key);
        this[options.key] = item;
        if (options.el.append) {
            options.el.append(item.html);
            if (options.type == 'CKeditor') {
                item.render();
            };
        } else {
            console.error('form => 未找到指定元素进行渲染 ：' + options.key);
        };
    };
    form.prototype.get = function (callback) {
        var data = {};
        var oldData = util.clone(this.$oldData);
        var valueObject = this.$formElementKey;
        var errorMessage = null;
        var errorElement = null;
        var errorkey = null;
        for (let i = 0; i < valueObject.length; i++) {
            const element = valueObject[i];
            if (this.hasOwnProperty(element)) {
                this[element].get((error, value) => {
                    if (error && !errorMessage) {
                        errorMessage = error;
                        errorElement = this[element];
                        errorkey = element;
                    } else {
                        data[element] = value;
                    }
                });
            } else {
                console.error('form => 获取 key : ' + element + ' 时，未找到该元素');
            };
        };
        var _isCompleteData = null;
        if (errorMessage == null) {
            this.errorMessage = null;
            if (this.$type == 'all') {
                _isCompleteData = data;
            } else if (this.$type == 'mergeByOldData') {
                _isCompleteData = $.extend({}, oldData, data);
            } else if (this.$type == 'onlyChange') {
                _isCompleteData = this.$mergeData(data, oldData);
            } else if (this.$type == 'mergeByOldDataChange') {
                _isCompleteData = this.$mergeData(data, oldData);
            };
            callback(_isCompleteData);
        } else {
            if (typeof this.$event.$onScrollError == 'function') {
                this.$event.$onScrollError(errorMessage, errorElement, errorkey);
            } else {
                alert.error({
                    title: '',
                    text: errorMessage,
                });
                // layer.msg(errorMessage, { icon: 5, shift: 6 });
            };
        };
    };
    form.prototype.$mergeData = function (data, oldData) {
        var returnData = $.extend({}, oldData);
        var _length = 0;
        for (var key in data) {
            if (data.hasOwnProperty(key)) {
                _length++;
                var formDataItem = data[key];
                if (verify.is('object', formDataItem)) {
                    var addKeyArray = [];
                    for (var checkBoxKey in formDataItem) {
                        if (formDataItem.hasOwnProperty(checkBoxKey)) {
                            var element = formDataItem[checkBoxKey];
                            if (element != returnData[key][checkBoxKey]) {
                                addKeyArray.push(checkBoxKey);
                            };
                        };
                    };
                    if (addKeyArray.length == 0) {
                        _length--;
                        delete returnData[key]
                    } else {
                        returnData[key] = {};
                        for (var i = 0; i < addKeyArray.length; i++) {
                            var element = addKeyArray[i];
                            returnData[key][element] = formDataItem[element];
                        }
                    };
                } else {
                    if (formDataItem == returnData[key]) {
                        _length--;
                        delete returnData[key];
                    } else {
                        returnData[key] = formDataItem;
                    };
                };
            }
        };
        if (_length == 0) {
            this.errorMessage = '未对表单进行任何修改';
            return false;
        } else {
            this.errorMessage = null;
            return returnData;
        };
    };
    form.prototype.$changeReadonlyForAll = function (type) {
        for (let i = 0; i < this.$formElementKey.length; i++) {
            const element = this.$formElementKey[i];
            if (this[element].readonly) {
                this[element].readonly(type);
            };
        };
    };
    form.prototype.$clearAll = function () {
        for (let i = 0; i < this.$formElementKey.length; i++) {
            const element = this.$formElementKey[i];
            if (this[element].clear) {
                this[element].clear();
            };
        };
    };
    form.prototype.render = function () {
        return this.html;
    };
    return new form();
};


export default formEvent
